/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package descriptor;

import java.io.IOException;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.jdom.*;
import org.jdom.input.DOMBuilder;
import org.xml.sax.SAXException;

/**
 *
 * @author KAV
 */
public class XmlParser implements Initializer {

    private ManagedObject mo;
    private String path;
    private static final String XML_TITLE = "title";
    private static final String XML_ENTITY_TEMPLATES = "entity-templates";
    private static final String XML_ENTITY_TEMPLATE = "entity-template";
    private static final String XML_DATABASE = "database-connection";
    private static final String XML_STRING = "string";
    private static final String XML_ATTR_FILENAME = "filename";
    private static final String XML_ATTR_ALIAS = "alias";
    private static final String XML_ATTR_TABLENAME = "table-name";
    private static final String XML_NAME = "name";
    private static final String XML_PROPERTIES = "properties";
    private static final String XML_PROPERTY = "property";
    private static final String XML_ATTR_TYPE = "type";
    private static final String XML_ATTR_PRYMARYKEY = "primary-key";
    private static final String XML_ATTR_NOTNULL = "not-null";
    private static final String XML_ATTR_NULLREPLACINGVALUE = "null-replacing-value";
    private static final String XML_PRESENTATIONS = "presentations";
    private static final String XML_PRESENTATION = "presentation";
    private static final String XML_EXTERNALS = "externals";
    private static final String XML_EXTERNAL = "external";
    private static final String XML_ATTR_LINK = "link";
    private static final String XML_ATTR_MODE = "mode";

    public XmlParser(String appDescriptor) {
        path = appDescriptor;
    }

    @Override
    public Object init(Object obj) {
        if (mo == ManagedObject.Application) {
            return (parseApplication(path));
        } else if (mo == ManagedObject.Template) {
            return (parseTemplate(path));
        }
        return null;
    }

    @Override
    public void setManagedObject(ManagedObject obj) {
        mo = obj;
    }

    public Object parseApplication(String resource) {
        Map<String, Object> map = new TreeMap<String, Object>();
        Collection<Template> templateCollection = new LinkedList<Template>();
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DOMBuilder builder2 = new DOMBuilder();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder2.build(builder.parse(resource));
            Element root = document.getRootElement();
            List children = root.getChildren();
            for (int i = 0; i < children.size(); i++) {
                Element e = (Element) children.get(i);
                if (e.getName().equals(XML_TITLE)) {
                    map.put("title", e.getText());
                } else if (e.getName().equals(XML_DATABASE)) {
                    map.put("connectionString", e.getAttributeValue(XML_STRING));
                } else if (e.getName().equals(XML_ENTITY_TEMPLATES)) {
                    List templates = e.getChildren();
                    for (int j = 0; j < templates.size(); j++) {
                        Element e2 = (Element) templates.get(j);
                        if (e2.getName().equals(XML_ENTITY_TEMPLATE)) {
                            setManagedObject(ManagedObject.Template);
                            Template t = (Template) parseTemplate(e2.getAttributeValue(XML_ATTR_FILENAME));
                            templateCollection.add(t);
                        }
                    }
                    map.put("templates", templateCollection);
                }
            }
        } catch (ParserConfigurationException e) {
            throw new RuntimeException();
        } catch (IOException e) {
            throw new RuntimeException();
        } catch (SAXException e) {
            throw new RuntimeException();
        }
        return map;
    }

    public Object parseTemplate(String resource) {
        Collection<PropertyTemplate> propertyTemplates = new LinkedList<PropertyTemplate>();
        Collection<PresentationTemplate> presentationTemplates = new LinkedList<PresentationTemplate>();
        Map<String, Object> templateMap = new TreeMap<String, Object>();
        Template newTemplate;
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DOMBuilder builder2 = new DOMBuilder();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder2.build(builder.parse(resource));
            Element root = document.getRootElement();
            templateMap.put(XML_ATTR_ALIAS, root.getAttributeValue(XML_ATTR_ALIAS));
            templateMap.put(XML_ATTR_TABLENAME, root.getAttributeValue(XML_ATTR_TABLENAME));
            List children = root.getChildren();
            for (int i = 0; i < children.size(); i++) {
                Element e = (Element) children.get(i);
                if (e.getName().equals(XML_NAME)) {
                    templateMap.put(XML_NAME, e.getText());
                } else if (e.getName().equals(XML_PROPERTIES)) {
                    List properties = e.getChildren();
                    for (int j = 0; j < properties.size(); j++) {
                        Element e2 = (Element) properties.get(j);
                        if (e2.getName().equals(XML_PROPERTY)) {
                            propertyTemplates.add(new PropertyTemplate(e2.getAttributeValue(XML_NAME), e2.getAttributeValue(XML_ATTR_TYPE), Boolean.parseBoolean(e2.getAttributeValue(XML_ATTR_PRYMARYKEY)), Boolean.parseBoolean(e2.getAttributeValue(XML_ATTR_NOTNULL)), e2.getAttributeValue(XML_ATTR_NULLREPLACINGVALUE)));
                        }
                    }
                } else if (e.getName().equals(XML_PRESENTATIONS)) {
                    List presentaions = e.getChildren();
                    for (int j = 0; j < presentaions.size(); j++) {
                        Element e2 = (Element) presentaions.get(j);
                        if (e2.getName().equals(XML_PRESENTATION)) {
                            Collection<External> newExternalsColl = new LinkedList<External>();
                            List parametrs = e2.getChildren();
                            Map<String, Object> paramCol = new TreeMap<String, Object>();
                            for (int k = 0; k < parametrs.size(); k++) {
                                Element e3 = (Element) parametrs.get(k);
                                if (e3.getName().equals(XML_NAME)) {
                                    paramCol.put(XML_NAME, e3.getText());
                                } else if (e3.getName().equals(XML_ATTR_NULLREPLACINGVALUE)) {
                                    paramCol.put(XML_ATTR_NULLREPLACINGVALUE, e3.getText());
                                } else if (e3.getName().equals(XML_EXTERNALS)) {
                                    List externals = e3.getChildren();
                                    for (int q = 0; q < externals.size(); q++) {
                                        Element e4 = (Element) externals.get(q);
                                        if (e4.getName().equals(XML_EXTERNAL)) {
                                            String mode = e4.getAttributeValue(XML_ATTR_MODE);
                                            newExternalsColl.add(new External(e4.getAttributeValue(XML_ATTR_LINK), e4.getAttributeValue("presentation"), (mode == null) ? false:mode.equals("replacing")));
                                        }
                                    }
                                }
                            }
                            presentationTemplates.add(new PresentationTemplate(e2.getAttributeValue(XML_PROPERTY), e2.getAttributeValue(XML_ATTR_TYPE), (String) paramCol.get(XML_NAME), (String) paramCol.get(XML_ATTR_NULLREPLACINGVALUE), e2.getAttributeValue(XML_ATTR_ALIAS),newExternalsColl));
                        }
                    }
                }
            }
            newTemplate = new Template((String) templateMap.get(XML_NAME), root.getAttributeValue(XML_ATTR_ALIAS), root.getAttributeValue(XML_ATTR_TABLENAME), propertyTemplates, presentationTemplates);
        } catch (ParserConfigurationException e) {
            throw new RuntimeException();
        } catch (IOException e) {
            throw new RuntimeException();
        } catch (SAXException e) {
            throw new RuntimeException();
        }
        return newTemplate;
        /*TreeMap<String, Object> map = new TreeMap<String, Object>();
        try {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DOMBuilder builder2 = new DOMBuilder();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder2.build(builder.parse(resource));
        Element root = document.getRootElement();
        map.put(XML_ATTR_ALIAS, root.getAttributeValue(XML_ATTR_ALIAS));
        map.put(XML_ATTR_TABLENAME, root.getAttributeValue(XML_ATTR_TABLENAME));
        List children = root.getChildren();
        for (int i = 0; i < children.size(); i++) {
        Element e = (Element) children.get(i);
        if (e.getName().equals(XML_NAME)) {
        map.put(XML_NAME, e.getText());
        }else if (e.getName().equals(XML_PROPERTIES)){
        List properties=e.getChildren();
        List<TreeMap<String,Object>> propertiesList=new LinkedList<TreeMap<String, Object>>();
        for (int j=0;j<properties.size();j++){
        Element e2=(Element) properties.get(j);
        if (e2.getName().equals(XML_PROPERTY)){
        TreeMap<String,Object> propertiesMap=new TreeMap<String, Object>();
        propertiesMap.put(XML_NAME, e2.getAttributeValue(XML_NAME));
        propertiesMap.put(XML_ATTR_TYPE, e2.getAttributeValue(XML_ATTR_TYPE));
        propertiesMap.put(XML_ATTR_PRYMARYKEY,e2.getAttributeValue(XML_ATTR_PRYMARYKEY));
        propertiesMap.put(XML_ATTR_NOTNULL,e2.getAttributeValue(XML_ATTR_NOTNULL));
        propertiesMap.put(XML_ATTR_NULLREPLACINGVALUE,e2.getAttributeValue(XML_ATTR_NULLREPLACINGVALUE));
        propertiesList.add(propertiesMap);
        }
        }
        map.put(XML_PROPERTIES, propertiesList);
        }else if (e.getName().equals(XML_PRESENTATIONS)){
        List presentaions=e.getChildren();
        List<TreeMap<String,Object>> presentationsList=new LinkedList<TreeMap<String, Object>>();
        for (int j=0;j<presentaions.size();j++){
        Element e2=(Element) presentaions.get(j);
        if (e2.getName().equals(XML_PRESENTATION)){
        TreeMap<String,Object> presentationsMap=new TreeMap<String, Object>();
        presentationsMap.put(XML_ATTR_TYPE, e2.getAttributeValue(XML_ATTR_TYPE));
        presentationsMap.put(XML_PROPERTY,e2.getAttributeValue(XML_PROPERTY));
        List parametrs=e2.getChildren();
        Map<String,Object> paramCol=new TreeMap<String,Object>();
        for (int k=0;k<parametrs.size();k++){
        Element e3=(Element)parametrs.get(k);
        if (e3.getName().equals(XML_NAME)){
        paramCol.put(XML_NAME, e3.getText());
        }else if (e3.getName().equals(XML_ATTR_NULLREPLACINGVALUE)){
        paramCol.put(XML_ATTR_NULLREPLACINGVALUE,e3.getText());
        }else if(e3.getName().equals(XML_EXTERNALS)){
        List externals=e3.getChildren();
        List<TreeMap<String,Object>> externalsList=new LinkedList<TreeMap<String, Object>>();
        for (int q=0;q<externals.size();q++){
        Element e4=(Element) externals.get(q);
        if (e4.getName().equals(XML_EXTERNAL)){
        TreeMap<String,Object> externalsMap=new TreeMap<String, Object>();
        externalsMap.put(XML_ATTR_LINK, e4.getAttributeValue(XML_ATTR_LINK));
        externalsMap.put(XML_PROPERTY, e4.getAttributeValue(XML_PROPERTY));
        externalsMap.put(XML_ATTR_MODE, e4.getAttributeValue(XML_ATTR_MODE));
        externalsList.add(externalsMap);
        }
        }
        paramCol.put(XML_EXTERNALS,externalsList);
        }
        }
        presentationsMap.put("params",paramCol);
        presentationsList.add(presentationsMap);
        }
        }
        map.put(XML_PRESENTATIONS, presentationsList);
        }
        }

        } catch (ParserConfigurationException e) {
        throw new RuntimeException();
        } catch (IOException e) {
        throw new RuntimeException();
        } catch (SAXException e) {
        throw new RuntimeException();
        }
        return map;*/
    }
}
